package com.yxw.yxnet_cd_center.customer_service.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yxw.yxnet_cd_center.common.dto.PageVO;
import com.yxw.yxnet_cd_center.common.exception.BaseException;
import com.yxw.yxnet_cd_center.common.utils.BaseDateTime;
import com.yxw.yxnet_cd_center.customer_service.dto.RoleDTO;
import com.yxw.yxnet_cd_center.customer_service.dto.RoleQueryDTO;
import com.yxw.yxnet_cd_center.customer_service.entity.YxCsMenuEntity;
import com.yxw.yxnet_cd_center.customer_service.entity.YxCsRoleEntity;
import com.yxw.yxnet_cd_center.customer_service.entity.YxCsRoleMenuEntity;
import com.yxw.yxnet_cd_center.customer_service.mapper.RelevancyMapper;
import com.yxw.yxnet_cd_center.customer_service.mapper.RoleMapper;
import com.yxw.yxnet_cd_center.customer_service.mapper.UserEmpMapper;
import com.yxw.yxnet_cd_center.customer_service.service.IRoleService;
import com.yxw.yxnet_cd_center.customer_service.service.SysMenuService;
import com.yxw.yxnet_cd_center.customer_service.utils.PageUtils;
import com.yxw.yxnet_cd_center.customer_service.vo.RoleVO;
import com.yxw.yxnet_cd_center.customer_service.vo.YxCsMenuVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 角色管理Service业务层处理
 *
 * @author xiexuxin
 * @date 2023-09-18
 */
@Slf4j
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, YxCsRoleEntity> implements IRoleService {

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private UserEmpMapper userMapper;

    @Autowired
    private RelevancyMapper relevancyMapper;

    @Autowired
    private SysMenuService menuService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addRole(RoleDTO roleDTO) {
        log.info("开始处理【添加角色】的业务，参数：{}", roleDTO);
        // 判断角色名称是否已存在
        LambdaQueryWrapper<YxCsRoleEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(true, YxCsRoleEntity::getRoleName, roleDTO.getRoleName());
        Integer count = roleMapper.selectCount(queryWrapper);
        if (count > 0) {
            throw new BaseException("角色名称【" + roleDTO.getRoleName() + "】已存在，请修改名称");
        }
        // 创建角色实体对象，并复制属性值
        YxCsRoleEntity roleEntity = new YxCsRoleEntity();
        BeanUtil.copyProperties(roleDTO, roleEntity);
        roleEntity.setRoleName(roleDTO.getRoleName());
        roleEntity.setStatus(null == roleEntity.getStatus() ? 1 : roleEntity.getStatus());
        roleEntity.setRemark(roleDTO.getRemark());
        roleEntity.setCreateTime(LocalDateTime.now());
        // 执行插入操作
        int rows = roleMapper.insert(roleEntity);
        // 判断插入操作是否成功
        if (rows != 1) {
            throw new BaseException("添加角色失败，服务器忙，请稍后再尝试！");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteRoleById(Long roleId) {
        log.info("开始处理【删除角色】的业务，参数：{}", roleId);
        // 查询待删除的角色是否存在
        RoleVO queryResult = selectRoleById(roleId);
        // 判断角色是否存在
        if (queryResult == null || queryResult.getRoleId() == 0) {
            throw new BaseException("删除角色失败，尝试删除的角色数据不存在！");
        }
        // 执行删除操作
        int rows = roleMapper.deleteById(roleId);
        // 判断删除操作是否成功
        if (rows != 1) {
            throw new BaseException("删除角色失败，服务器忙，请稍后再试！");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteByRoleIds(List<Long> roleIds) {
        log.info("开始处理【批量删除角色】的业务，参数：{}", roleIds);
        // 判断待删除的角色列表是否为空
        if (CollectionUtils.isEmpty(roleIds)) {
            throw new BaseException("删除角色失败，尝试删除的角色数据不存在！");
        }
        // 执行批量删除操作
        int rows = roleMapper.deleteByRoleIds(roleIds);
        // 判断删除操作是否成功
        if (rows != roleIds.size()) {
            throw new BaseException("删除角色失败，服务器忙，请稍后再试！");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRoleStatusById(Long roleId) {
        log.info("开始处理【修改角色状态】的业务，参数：{}", roleId);
        roleMapper.updateRoleStatusById(roleId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRole(Long roleId, RoleDTO roleDTO) {
        log.info("开始处理【修改角色】的业务，参数：{}", roleDTO);
        // 查询待修改的角色是否存在
        RoleVO queryResult = roleMapper.selectRoleById(roleId);
        // 判断角色是否存在
        if (queryResult == null || queryResult.getRoleId() == 0) {
            throw new BaseException("修改角色失败，尝试修改的角色数据不存在！");
        }
        // 判断角色名称是否已被占用
        int count = countByNameAndNotId(roleId, roleDTO.getRoleName());
        if (count > 0) {
            throw new BaseException("修改角色失败，角色名称已经被占用！");
        }
        // 创建角色实体对象，并复制属性值
        YxCsRoleEntity roleEntity = new YxCsRoleEntity();
        BeanUtils.copyProperties(roleDTO, roleEntity);
        roleEntity.setRoleId(roleId);
        roleEntity.setUpdateTime(LocalDateTime.now());
        // 执行更新操作
        int rows = roleMapper.updateById(roleEntity);
        // 判断更新操作是否成功
        if (rows != 1) {
            throw new BaseException("修改角色失败，服务器忙，请稍后再试！");
        }
    }

    @Override
    public int countByNameAndNotId(Long roleId, String roleName) {
        log.info("开始执行【统计匹配名称查不匹配ID的角色数量】，Id：{}，名称：{}", roleId, roleName);
        QueryWrapper<YxCsRoleEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("role_name", roleName).ne("role_id", roleId);
        return roleMapper.selectCount(queryWrapper);
    }

    @Override
    public RoleVO selectRoleById(Long roleId) {
        log.info("开始处理【根据id查询角色】的业务，参数：{}", roleId);
        return roleMapper.selectRoleById(roleId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRoleMenuByRoleId(List<YxCsRoleMenuEntity> roleMenus) {
        log.info("开始处理【角色编辑权限】的业务，参数：{}", roleMenus);
        // 删除原有角色菜单关联关系
        for (YxCsRoleMenuEntity roleMenu : roleMenus) {
            Long roleId = roleMenu.getRoleId();
            List<Long> menuIds = relevancyMapper.selectMenuIdsByRoleId(roleId).stream().distinct().collect(Collectors.toList());
            if (!menuIds.isEmpty()) {
                relevancyMapper.deleteRoleMenuByRoleId(roleId);
            }
        }
        // 如果roleMenus中的menuIds为空，则不执行后续处理逻辑
        if (roleMenus.stream().anyMatch(roleMenu -> roleMenu.getMenuIds() == null || roleMenu.getMenuIds().length == 0)) {
            return;
        }
        // 构建新的角色菜单关联关系
        List<YxCsRoleMenuEntity> newRoleMenus = new ArrayList<>();
        for (YxCsRoleMenuEntity roleMenu : roleMenus) {
            Long roleId = roleMenu.getRoleId();
            Long[] menuIds = roleMenu.getMenuIds();
            Set<Long> menuIdSet = new HashSet<>();
            for (Long menuId : menuIds) {
                addMenuAndParents(menuId, menuIdSet);
            }
            YxCsRoleMenuEntity newRoleMenu = new YxCsRoleMenuEntity();
            Long[] menuIdArray = menuIdSet.toArray(new Long[0]);
            newRoleMenu.setMenuIds(menuIdArray);
            newRoleMenu.setRoleId(roleId);
            newRoleMenus.add(newRoleMenu);
        }
        // 插入新的角色菜单关联关系
        relevancyMapper.insertRoleMenus(newRoleMenus);
    }

    // 查询菜单ID及其父节点ID的方法
    private Long selectParentIdByMenuId(Long menuId) {
        YxCsMenuEntity menu = menuService.selectMenuById(menuId);
        if (menu != null) {
            return menu.getParentId();
        }
        return null;
    }

    private void addMenuAndParents(Long menuId, Set<Long> menuIdSet) {
        Long parentId = selectParentIdByMenuId(menuId);
        if (parentId != null) {
            if (!menuIdSet.contains(parentId) && parentId != 0) {
                menuIdSet.add(parentId);
                addMenuAndParents(parentId, menuIdSet);
            }
        }
        if (!menuIdSet.contains(menuId) && menuId != 0) {
            menuIdSet.add(menuId);
        }
    }


    @Override
    public PageVO<RoleVO> selectRoleByUserId(Long userId) {
        log.info("开始处理【根据用户id查询拥有角色】的业务，参数：{}", userId);
        RoleQueryDTO roleQueryDTO = new RoleQueryDTO();
        Page<RoleVO> page = new Page<>(roleQueryDTO.getCurrPage(), roleQueryDTO.getPageSize());
        List<RoleVO> list = roleMapper.selectRoleByUserId(userId);
        return PageUtils.get(page, list);
    }

    @Override
    public PageVO<RoleVO> getRoleList(RoleQueryDTO roleQueryDTO) {
        log.info("开始处理【条件查询角色列表】的业务，条件参数：{}", roleQueryDTO);
        // 创建分页对象
        Page<YxCsRoleEntity> page = new Page<>(roleQueryDTO.getCurrPage(), roleQueryDTO.getPageSize());
        // 创建查询条件构造器
        LambdaQueryWrapper<YxCsRoleEntity> queryWrapper = new LambdaQueryWrapper<>();
        // 获取查询条件参数
        String roleName = StringUtils.trimToNull(roleQueryDTO.getRoleName());
        String createDateStart = roleQueryDTO.getCreateTimeStart();
        String createDateEnd = roleQueryDTO.getCreateTimeEnd();
        queryWrapper
                .like(StringUtils.isNotBlank(roleName), YxCsRoleEntity::getRoleName, roleName)
                .eq(StringUtils.isNotBlank(roleQueryDTO.getStatus()), YxCsRoleEntity::getStatus, roleQueryDTO.getStatus())
                .ge(StringUtils.isNotBlank(roleQueryDTO.getCreateTimeStart()), YxCsRoleEntity::getCreateTime, BaseDateTime.getDate(roleQueryDTO.getCreateTimeStart()));
        // 添加创建时间范围条件
        if (StringUtils.isNotBlank(createDateStart) && StringUtils.isNotBlank(createDateEnd)) {
            queryWrapper.apply("DATE(create_time) BETWEEN {0} AND {1}", createDateStart, createDateEnd);
        }
        // 分页查询角色数据
        page = baseMapper.selectPage(page, queryWrapper);
        List<YxCsRoleEntity> entityList = page.getRecords();
        // 将实体对象转换为VO对象
        List<RoleVO> listVoList = new ArrayList<>();
        if (null != entityList && !entityList.isEmpty()) {
            listVoList = BeanUtil.copyToList(entityList, RoleVO.class);
        }
        // 封装分页结果并返回
        return PageUtils.get(page, listVoList);
    }

    @Override
    public List<RoleVO> roleList() {
        log.info("开始处理【查询角色列表】的业务，无参数");
        return roleMapper.roleList();
    }

    @Override
    public List<RoleVO> roleListByStatus() {
        log.info("开始处理【查询启动角色列表】的业务，无参数");
        return roleMapper.roleListByStatus();
    }

    @Override
    public List<YxCsMenuVo> getMenuTreeByRoleMenu(Long roleId) {
        List<YxCsRoleMenuEntity> roleMenu = relevancyMapper.selectRoleMenuByRoleId(roleId);
        if (roleMenu.isEmpty()) {
            return null;
        }
        // 根据角色ID查询关联的菜单ID列表
        List<Long> menuIds = relevancyMapper.selectMenuIdsByRoleId(roleId).stream().distinct().collect(Collectors.toList());
        // 根据菜单ID列表查询菜单列表
        List<YxCsMenuEntity> menuList = userMapper.selectList(menuIds);
        List<YxCsMenuVo> menuVos = BeanUtil.copyToList(menuList, YxCsMenuVo.class);
        return buildMenuTree(menuVos, 0L);
    }

    private List<YxCsMenuVo> buildMenuTree(List<YxCsMenuVo> menuVos, Long parentId) {
        List<YxCsMenuVo> tree = new ArrayList<>();
        for (YxCsMenuVo menuVo : menuVos) {
            if (parentId.equals(menuVo.getParentId())) {
                List<YxCsMenuVo> children = buildMenuTree(menuVos, menuVo.getMenuId());
                menuVo.setChildren(children);
                tree.add(menuVo);
            }
        }
        return tree;
    }
}
